home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / others / html / gifmerge / gifmerge.c next >
C/C++ Source or Header  |  1997-08-13  |  16KB  |  646 lines

  1. /*
  2.  * gifmerge.c
  3.  *
  4.  * Copyright (C) 1990,1991,1992,1993 by Mark Podlipec. 
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified and redistributed
  8.  * without fee provided that this copyright notice is preserved 
  9.  * intact on all copies and modified copies.
  10.  * 
  11.  * There is no warranty or other guarantee of fitness of this software.
  12.  * It is provided solely "as is". The author(s) disclaim(s) all
  13.  * responsibility and liability with respect to this software's usage
  14.  * or its effect upon hardware or computer systems.
  15.  *
  16.  */
  17.  /*
  18.   * Description:
  19.   *
  20.   * This program reads a gif91(see XAnim docs) file and merges the listed
  21.   * gif files into one gif file. 
  22.   *
  23.   * Eventually, I'd like to have this program compare the current image
  24.   * with the previous image and check to see if only a small section of
  25.   * the screen changed from the previous image. Worth a shot.
  26.   */
  27.  
  28.  /*
  29.   * Rev 1.00    23Jul91    Mark Podlipec
  30.   *    creation
  31.   * Rev 1.01    08Jan92    Mark Podlipec
  32.   *     use all colormaps, not just 1st.
  33.   *
  34.   * Rev 1.2    20Dec95  Rene Mueller
  35.   *     command-line input (no longer txtfile needed)
  36.   *
  37.   * Rev 1.3    05Feb96  Rene Mueller (kiwi@iis.ee.ethz.ch)
  38.   *     GIF89a transparency, and "Netscape2.0" application extension (looping)
  39.   * Rev 1.31   14May96  Rene Mueller (kiwi@iis.ee.ethz.ch)
  40.   *     disposal selectable
  41.   * Rev 1.32   16Jul96  Rene Mueller (kiwi@iis.ee.ethz.ch)
  42.   *     logical position per image manipulating
  43.   * Rev 1.33   22Jul96  Rene Mueller (kiwi@iis.ee.ethz.ch)
  44.   *     -notransp and -nopos added
  45.   * Rev 1.34   13Aug97  Guido Flohr (gufl0000@stud.uni-sb.de)
  46.   *     -help added
  47.   *     -o added
  48.   *     exit code for Usage()
  49.   *     get program name from argv[0]
  50.   *     detect empty list of input files
  51.   *     revision number has now to be passed to cc with -DDA_REV=...
  52.   */
  53.  
  54. #include "gifmerge.h"
  55.  
  56. #define MAXVAL  4100            /* maxval of lzw coding size */
  57. #define MAXVALP 4200
  58.  
  59. int debug_flag = 0;  /* make these options */
  60. int verbose = 0;  /* make these options */
  61. int imagex = 0;
  62. int imagey = 0;
  63. int imagec = 0;
  64.  
  65. GIF_Color gif_cmap[256];
  66.  
  67. ULONG GIF_Get_Code();
  68. void GIF_Decompress();
  69. void GIF_Get_Next_Entry();
  70. void GIF_Add_To_Table();
  71. void GIF_Send_Data();
  72. void GIF_Clear_Table();
  73. void GIF_Screen_Header();
  74. void GIF_Image_Header();
  75. void GIF_Read_File();
  76.  
  77. GIF_Screen_Hdr gifscrn;
  78. GIF_Image_Hdr gifimage;
  79. GIF_Table table[MAXVALP];
  80.  
  81. ULONG root_code_size,code_size,CLEAR,EOI,INCSIZE;
  82. ULONG nextab;
  83. ULONG gif_mask[16] = {1,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,0,0};
  84. ULONG gif_ptwo[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,0,0};
  85. UBYTE gif_buff[MAXVALP];
  86. ULONG gif_block_size;
  87. int num_bits,bits;
  88.  
  89. int pic_i;
  90. char gif_file_name[256];
  91. int screen_was_last;
  92.  
  93. int disposal = 2;
  94. int repeats = -1;
  95. int delay = 50;
  96. int transp = -1;
  97. int pos_set = 0;
  98. int xpos = 0, ypos = 0;
  99.  
  100. FILE* out = stdout;  /* File to write to.  */
  101. const char* myname;
  102.  
  103. /* Open out file or die.  */
  104. void safe_wopen (filename)
  105. const char* filename;
  106. {
  107.   extern int errno;
  108.   
  109.   out = fopen (filename, "wb");
  110.   if (!out) {
  111.     fprintf (stderr, "%s: can\'t open `%s' for writing: %s\n", 
  112.         myname, filename, strerror (errno));
  113.     exit (1);
  114.   }
  115. }
  116.  
  117. void TheEnd()
  118. {
  119.  exit(0);
  120. }
  121.  
  122. void TheEnd1(p)
  123. char *p;
  124. {
  125.  fprintf(stderr,"%s",p);
  126.  TheEnd();
  127. }
  128.  
  129. Usage(excode)
  130. int excode;
  131. {
  132.   fprintf(stderr,"\nUsage:\n%s [-<r>,<g>,<b>] [-<delay>] [-l<loops>] [-d<disp>] *.gif > anim.gif\n\n", myname);
  133.   fprintf(stderr,"   -<r>,<g>,<b>   set transparency, ie -192,192,192, default: no transparency\n");
  134.   fprintf(stderr,"   -notransp      set transparency off (after you used -r,g,b before)\n");
  135.   fprintf(stderr,"   -<delay>       set delay of between images in 1/100th secs, ie -100\n                  default 50 (0.5secs)\n");
  136.   fprintf(stderr,"   -l<loops>      set loop counter, ie -l0 (ever) or -l1000, default no loops\n");
  137.   fprintf(stderr,"   -d<disposal>   set disposal 0 = no action, 1 = no dispose,\n");
  138.   fprintf(stderr,"                               2 = restore background (default)\n");
  139.   fprintf(stderr,"                               3 = restore previous\n");
  140.   fprintf(stderr,"   -pos<x>,<y>    set offset position for image\n");
  141.   fprintf(stderr,"   -nopos         reset offset position (default)\n");
  142.   fprintf(stderr,"   -o<outfile>    write to `outfile' instead of stderr\n");
  143.   fprintf(stderr,"   -help          show this help screen and exit immediately\n");
  144.   fprintf(stderr,"\n   or look at http://www.iis.ee.ethz.ch/~kiwi/GIFMerge/\n\n");
  145.   exit(excode);
  146. }
  147.  
  148. main(argc,argv)
  149. int argc;
  150. char *argv[];
  151. {
  152.  int first, i;
  153.  int num_of_files,num_of_frames;
  154.  char* out_file_name = NULL;
  155.  
  156.  myname = argv[0];
  157.  
  158.  fprintf(stderr,"=== GIFMerge Rev %2.2f (C) 1991,1992 by Mark Podlipec\n    Improvements by Rene K. Mueller 1996\n    Modified by Guido Flohr 1997\n",DA_REV);
  159.  
  160.  if (argc < 2) Usage(1);
  161.  
  162.  screen_was_last = FALSE;
  163.  
  164.  num_of_files = argc-1;
  165.  
  166.  /* Read files, save colormap of 1st one only
  167.   */
  168.  first = 1;
  169.  for(i=0; i<num_of_files; i++)
  170.  {
  171.    unsigned int r,g,b;
  172.    if(sscanf(argv[i+1],"-%u,%u,%u",&r,&g,&b)==3) {
  173.       transp = r|(g<<8)|(b<<16);
  174.       fprintf(stderr,"Transparency: %d %d %d\n",r,g,b);
  175.    } else if(!strcmp(argv[i+1],"-notransp"))
  176.       transp = -1, fprintf(stderr,"NoTransparency\n");
  177.    else if(sscanf(argv[i+1],"-%u",&delay)==1)
  178.       fprintf(stderr,"Delay: %d (%.2f secs)\n",delay,delay/100.);
  179.    else if(sscanf(argv[i+1],"-l%d",&repeats)==1)
  180.       fprintf(stderr,"Loops: %d\n",repeats);
  181.    else if(sscanf(argv[i+1],"-d%d",&disposal)==1)
  182.       fprintf(stderr,"DisposalMode: %d\n",disposal);
  183.    else if(sscanf(argv[i+1],"-pos%d,%d",&xpos,&ypos)==2)
  184.       fprintf(stderr,"Position: %d %d\n",xpos,ypos), pos_set = 1;
  185.    else if(!strcmp(argv[i+1],"-nopos"))
  186.       pos_set = 0, fprintf(stderr,"NoPositioning\n");
  187.    else if(!strncmp(argv[i + 1], "-o", 2)) {
  188.      out_file_name = &argv[i + 1][2];
  189.      if (out_file_name[0] == '\000') {
  190.        fprintf (stderr, "\n%s: option -o requires an argument\n", myname);
  191.        Usage (1);
  192.      }
  193.    } else if (!strcmp (argv[i + 1], "-help"))
  194.      Usage (0);
  195.    else if(argv[i+1][0]=='-')
  196.       Usage(1);
  197.    else {
  198.      if (first != 0 && out_file_name)
  199.        safe_wopen (out_file_name);
  200.      strcpy(gif_file_name,argv[i+1]);
  201.      fprintf(stderr,"Merging %s ...\n",gif_file_name);
  202.      GIF_Read_File(gif_file_name,first);
  203.      first = 0;
  204.    }
  205.  }
  206.  if (first != 0) {
  207.    fprintf (stderr, "\n%s: no input files\n", myname);
  208.    Usage (1);
  209.  }
  210.  fputc(';',out); /* image separator */
  211.  if (out_file_name)
  212.    if (fclose (out) != 0) {
  213.      extern int errno;
  214.      fprintf (stderr, "%s: can\'t close `%s\': %s\n",
  215.          myname, out_file_name, strerror (errno));
  216.      exit (1);
  217.    }
  218.  exit(0);
  219. }
  220.  
  221.  
  222. /*
  223.  * Read a GIF file, outputting to fname as we go.
  224.  * It would be faster to read and write the individual blocks,
  225.  * but eventually we'd like to optimize based on changes from
  226.  * previous images(ie only a small section of the image changed.
  227.  */
  228. void
  229. GIF_Read_File(fname,first_image)
  230. char *fname;
  231. int first_image;
  232. {
  233.  FILE *fp;
  234.  int ret,i,exit_flag;
  235.  
  236.  if ( (fp=fopen(fname,"r"))==0)
  237.  { 
  238.   extern int errno;
  239.   fprintf(stderr,"%s: can\'t open %s for reading.\n",myname,fname,strerror (errno)); 
  240.   TheEnd();
  241.  }
  242.  
  243.  GIF_Screen_Header(fp,out,first_image);
  244.  
  245.  /*** read until  ,  separator */
  246.  do
  247.  {
  248.   i=fgetc(fp);
  249.   if ( (i<0) && feof(fp))
  250.   {
  251.    fclose(fp);
  252.    TheEnd1("GIF_Read_Header: Unexpected End of File\n");
  253.   }
  254.  } while(i != ',');
  255.  
  256.  fputc(',',out); /* image separator */
  257.  
  258.  GIF_Image_Header(fp,out,first_image);
  259.  
  260.  /*** Setup ACTION for IMAGE */
  261.  
  262.  GIF_Decompress(fp,out,0);
  263.  fputc(0,out);  /* block count of zero */
  264.  
  265.  fclose(fp);
  266. }
  267.  
  268. void GIF_Decompress(fp,fout)
  269. FILE *fp,*fout;
  270. {
  271.  register ULONG code,old;
  272.  
  273.  pic_i = 0;
  274.  bits=0;
  275.  num_bits=0;
  276.  gif_block_size=0;
  277.     /* starting code size of LZW */
  278.  root_code_size=(fgetc(fp) & 0xff); fputc(root_code_size,fout);
  279.  GIF_Clear_Table();                /* clear decoding symbol table */
  280.  
  281.  code=GIF_Get_Code(fp,fout);
  282.  
  283.  if (code==CLEAR) 
  284.  {
  285.   GIF_Clear_Table(); 
  286.   code=GIF_Get_Code(fp,fout);
  287.  }
  288.  /* write code(or what it currently stands for) to file */
  289.  GIF_Send_Data(code);   
  290.  old=code;
  291.  code=GIF_Get_Code(fp,fout);
  292.  do
  293.  {
  294.   if (table[code].valid==1)    /* if known code */
  295.   {
  296.        /* send it's associated string to file */
  297.     GIF_Send_Data(code);
  298.     GIF_Get_Next_Entry(fp);       /* get next table entry (nextab) */
  299.     GIF_Add_To_Table(old,code,nextab);  /* add old+code to table */
  300.     old=code;
  301.   }
  302.   else      /* code doesn't exist */
  303.   {
  304.     GIF_Add_To_Table(old,old,code);   /* add old+old to table */
  305.     GIF_Send_Data(code);
  306.     old=code;
  307.   }
  308.   code=GIF_Get_Code(fp,fout);
  309.   if (code==CLEAR)
  310.   { 
  311.    GIF_Clear_Table();
  312.    code=GIF_Get_Code(fp,fout);
  313.    GIF_Send_Data(code);
  314.    old=code;
  315.    code=GIF_Get_Code(fp,fout);
  316.   }
  317.  } while(code!=EOI);
  318. }
  319.  
  320. void GIF_Get_Next_Entry(fp)
  321. FILE *fp;
  322. {
  323.    /* table walk to empty spot */
  324.  while(  (table[nextab].valid==1)
  325.        &&(nextab<MAXVAL)
  326.       ) nextab++;
  327.  /* 
  328.   * Ran out of space??!?  Something's roached 
  329.   */
  330.  if (nextab>=MAXVAL)    
  331.  { 
  332.   fprintf(stderr,"%s: error: GetNext nextab=%ld\n",myname,nextab);
  333.   fclose(fp);
  334.   TheEnd();
  335.  }
  336.  if (nextab==INCSIZE)   /* go to next table size (and LZW code size ) */
  337.  {
  338.    /* fprintf(stderr,"GetNext INCSIZE was %ld ",nextab); */
  339.    code_size++; INCSIZE=(INCSIZE*2)+1;
  340.    if (code_size>=12) code_size=12;
  341. /*   fprintf(stderr,"<%ld>",INCSIZE); */
  342.  }
  343.  
  344. }
  345. /*  body is associated string
  346.     next is code to add to that string to form associated string for
  347.     index
  348. */     
  349.  
  350. void GIF_Add_To_Table(body,next,index)
  351. register ULONG body,next,index;
  352. {
  353.  if (index>MAXVAL)
  354.  { 
  355.   fprintf(stderr,"%s: error index=%ld\n",myname,index);
  356.  }
  357.  else
  358.  {
  359.   table[index].valid=1;
  360.   table[index].data=table[next].first;
  361.   table[index].first=table[body].first;
  362.   table[index].last=body;
  363.  }
  364. }
  365.  
  366. void GIF_Send_Data(index)
  367. register int index;
  368. {
  369.  register int i,j;
  370.  i=0;
  371.  do         /* table walk to retrieve string associated with index */
  372.  { 
  373.   gif_buff[i]=table[index].data; 
  374.   i++;
  375.   index=table[index].last;
  376.   if (i>MAXVAL)
  377.   { 
  378.    fprintf(stderr,"%s: error: Sending i=%ld index=%ld\n",myname,i,index);
  379.    TheEnd();
  380.   }
  381.  } while(index>=0);
  382.  
  383.  /* now invert that string since we retreived it backwards */
  384.  i--;
  385.  for(j=i;j>=0;j--)
  386.  {
  387.   /*pic[pic_i] = gif_buff[j] | gif_pix_offset;*/
  388.   pic_i++;
  389.  }
  390. }
  391.  
  392.  
  393. /* 
  394.  * initialize string table 
  395.  */
  396. void GIF_Init_Table()       
  397. {
  398.  register int maxi,i;
  399.  
  400. if (debug_flag) fprintf(stderr,"Initing Table...");
  401.  maxi=gif_ptwo[root_code_size];
  402.  for(i=0; i<maxi; i++)
  403.  {
  404.   table[i].data=i;   
  405.   table[i].first=i;
  406.   table[i].valid=1;  
  407.   table[i].last = -1;
  408.  }
  409.  CLEAR=maxi; 
  410.  EOI=maxi+1; 
  411.  nextab=maxi+2;
  412.  INCSIZE = (2*maxi)-1;
  413.  code_size=root_code_size+1;
  414. }
  415.  
  416.  
  417. /* 
  418.  * clear table 
  419.  */
  420. void GIF_Clear_Table()   
  421. {
  422.  register int i;
  423. if (debug_flag) fprintf(stderr,"Clearing Table...\n");
  424.  for(i=0;i<MAXVAL;i++) table[i].valid=0;
  425.  GIF_Init_Table();
  426. }
  427.  
  428. /*CODE*/
  429. ULONG GIF_Get_Code(fp,fout) /* get code depending of current LZW code size */
  430. FILE *fp,*fout;
  431. {
  432.  ULONG code;
  433.  register int tmp;
  434.  
  435.  while(num_bits < code_size)
  436.  {
  437.   /**** if at end of a block, start new block */
  438.   if (gif_block_size==0) 
  439.   {
  440.    tmp = fgetc(fp);
  441.    if (tmp >= 0 )
  442.    {
  443.     fputc(tmp,fout);
  444.     gif_block_size=(ULONG)(tmp);
  445.    }
  446.    else TheEnd1("EOF in data stream\n");
  447.   }
  448.  
  449.   tmp = fgetc(fp);   gif_block_size--;
  450.   if (tmp >= 0)
  451.   {
  452.    fputc(tmp,fout);
  453.    bits |= ( ((ULONG)(tmp) & 0xff) << num_bits );
  454.    num_bits+=8;
  455.   }
  456.   else TheEnd1("EOF in data stream\n");
  457.  }
  458.   
  459.  code = bits & gif_mask[code_size];
  460.  bits >>= code_size;
  461.  num_bits -= code_size; 
  462.  
  463.  
  464.  if (code>MAXVAL)
  465.  { 
  466.   fprintf(stderr,"\n%s: error! in stream=%lx \n",myname,code); 
  467.   fprintf(stderr,"CLEAR=%lx INCSIZE=%lx EOI=%lx code_size=%lx \n",
  468.                                            CLEAR,INCSIZE,EOI,code_size); 
  469.   code=EOI;
  470.  }
  471.  
  472.  if (code==INCSIZE)
  473.  {
  474.   if (code_size<12)
  475.   {
  476.    code_size++; INCSIZE=(INCSIZE*2)+1;
  477.   }
  478.   else if (debug_flag) fprintf(stderr,"<13?>"); 
  479.  }
  480.  
  481.  return(code);
  482. }
  483.  
  484.  
  485. /* 
  486.  * read GIF header 
  487.  */
  488. void GIF_Screen_Header(fp,fout,first_time)
  489. FILE *fp,*fout;
  490. int first_time;
  491. {
  492.  int temp,i;
  493.  
  494.  for(i=0;i<6;i++) {
  495.   temp = fgetc(fp);
  496. /*   if (first_time==TRUE) fputc(temp,fout); */
  497.  }
  498.  if(first_time) 
  499.    fputs("GIF89a",fout);
  500.  gifscrn.width  = GIF_Get_Short(fp,fout,first_time);
  501.  gifscrn.height = GIF_Get_Short(fp,fout,first_time);
  502.  temp=fgetc(fp);         if (first_time==TRUE) fputc(temp,fout);
  503.  gifscrn.m       =  temp & 0x80;
  504.  gifscrn.cres    = (temp & 0x70) >> 4;
  505.  gifscrn.pixbits =  temp & 0x07;
  506.  gifscrn.bc  = fgetc(fp);     if (first_time==TRUE) fputc(gifscrn.bc,fout);
  507.  temp=fgetc(fp);         if (first_time==TRUE) fputc(temp,fout);
  508.  imagec=gif_ptwo[(1+gifscrn.pixbits)];
  509.  
  510.  if (verbose)
  511.   fprintf(stderr,"Screen: %ldx%ldx%ld m=%ld cres=%ld bkgnd=%ld pix=%ld\n",
  512.     gifscrn.width,gifscrn.height,imagec,gifscrn.m,gifscrn.cres,
  513.     gifscrn.bc,gifscrn.pixbits);
  514.  
  515.  if (gifscrn.m)
  516.  {
  517.   for(i=0;i<imagec;i++)
  518.   {
  519.    gif_cmap[i].cmap.red   = temp = fgetc(fp); 
  520.            if (first_time==TRUE) fputc(temp,fout);
  521.    gif_cmap[i].cmap.green = temp = fgetc(fp); 
  522.            if (first_time==TRUE) fputc(temp,fout);
  523.    gif_cmap[i].cmap.blue  = temp = fgetc(fp); 
  524.            if (first_time==TRUE) fputc(temp,fout);
  525.   }
  526.  }
  527.  screen_was_last = TRUE;
  528.  if(gifscrn.m&&(transp>=0||delay>=0)) {
  529.    int ix = 0, max_dist = 3*256;
  530.    if(transp>=0) {
  531.       for(i=0; i<imagec; i++) {
  532.          int dist = 
  533.             abs(gif_cmap[i].cmap.red-(transp&255))+
  534.             abs(gif_cmap[i].cmap.green-((transp>>8)&255))+
  535.             abs(gif_cmap[i].cmap.blue-(transp>>16));
  536.          if(dist<max_dist) 
  537.             ix = i, max_dist = dist;
  538.       } 
  539.       if(max_dist==0)   /* info at http://www.iis.ee.ethz.ch/~kiwi/GIFMerge/gifspecs.txt */   
  540.          ;
  541. /*          fprintf(stderr,"Transparent color matched fully\n"); */
  542.       else
  543.          fprintf(stderr,"%s: Transparent not matched fully, col #%d (%d,%d,%d) used now\n",
  544.             myname,ix,gif_cmap[ix].cmap.red,gif_cmap[ix].cmap.green,gif_cmap[ix].cmap.blue);
  545.    }
  546.    fputc(0x21,fout);
  547.    fputc(0xF9,fout);
  548.    fputc(0x04,fout);
  549.    fputc((transp>=0?0x01:0x00)|(disposal<<2),fout);
  550.    fputc(delay&255,fout);
  551.    fputc((unsigned)delay>>8,fout);
  552.    fputc(ix,fout);
  553.    fputc(0x00,fout);
  554.  }
  555.  if(first_time&&repeats>=0) { /* documentation look at */
  556.    fputc(0x21,fout);          /* http://www.reiworld.com/royalef/gifabout.htm */
  557.    fputc(0xFF,fout);
  558.    fputc(0x0B,fout);
  559.    fputs("NETSCAPE2.0",fout);
  560.    fputc(0x03,fout);
  561.    fputc(0x01,fout);
  562.    fputc(repeats&255,fout);
  563.    fputc((unsigned)repeats>>8,fout);
  564.    fputc(0x00,fout);
  565.  }
  566. }
  567.  
  568. void GIF_Image_Header(fp,fout,first_time)
  569. FILE *fp,*fout;
  570. int first_time;
  571. {
  572.  int temp,tnum,i,tmp;
  573.  
  574.  tmp = GIF_Get_Short(fp,fout,0); if(!pos_set) xpos = tmp;
  575.  gifimage.left   = xpos; GIF_Put_Short(fout,xpos);
  576.  tmp = GIF_Get_Short(fp,fout,0); if(!pos_set) ypos = tmp;
  577.  gifimage.top    = ypos; GIF_Put_Short(fout,ypos);
  578.  gifimage.width  = GIF_Get_Short(fp,fout,1);
  579.  gifimage.height = GIF_Get_Short(fp,fout,1);
  580.  temp=fgetc(fp); 
  581.  
  582.  gifimage.m        = temp & 0x80;
  583.  gifimage.i        = temp & 0x40;
  584.  gifimage.pixbits  = temp & 0x07;
  585.  
  586.  if (screen_was_last && (first_time==FALSE)) temp |= 0x80;
  587.  temp &= 0xf8;
  588.  temp |= gifscrn.pixbits;
  589.  fputc(temp,fout);
  590.  
  591.  imagex=gifimage.width;
  592.  imagey=gifimage.height;
  593.  tnum=gif_ptwo[(1+gifimage.pixbits)];
  594.  if (verbose)
  595.   fprintf(stderr,"Image: %ldx%ldx%ld m=%ld i=%ld pix=%ld \n",
  596.     imagex,imagey,tnum,gifimage.m,gifimage.i,gifimage.pixbits);
  597.  
  598.  /* if there is an image cmap, then use it */
  599.  if (gifimage.m)
  600.  {
  601.   for(i=0;i<tnum;i++)
  602.   {
  603.    gif_cmap[i].cmap.red   = temp = fgetc(fp); fputc(temp,fout);
  604.    gif_cmap[i].cmap.green = temp = fgetc(fp); fputc(temp,fout);
  605.    gif_cmap[i].cmap.blue  = temp = fgetc(fp); fputc(temp,fout);
  606.   }
  607.  }  /* else if screen was last not 1st time */
  608.  else if (screen_was_last && (first_time==FALSE))
  609.  {
  610.   for(i=0;i<imagec;i++)
  611.   {
  612.    fputc(gif_cmap[i].cmap.red  ,fout);
  613.    fputc(gif_cmap[i].cmap.green,fout);
  614.    fputc(gif_cmap[i].cmap.blue ,fout);
  615.   }
  616.  }
  617.  screen_was_last = FALSE; 
  618. }
  619.  
  620.  
  621. /*
  622.  *
  623.  */
  624. int GIF_Get_Short(fp,fout,first_time)
  625. FILE *fp,*fout;
  626. int first_time;
  627. {
  628.  register int temp,tmp1;
  629.  temp=fgetc(fp);     if (first_time==TRUE) fputc(temp,fout);
  630.  tmp1=fgetc(fp);     if (first_time==TRUE) fputc(tmp1,fout);
  631.  return(temp|( (tmp1) << 8 ));
  632. }
  633.  
  634.  
  635. /*
  636.  *
  637.  */
  638. int GIF_Put_Short(fout,data)
  639. FILE *fout; unsigned int data;
  640. {
  641.  fputc((unsigned char)(data&255),fout);      /* lo */
  642.  fputc((unsigned char)((data>>8)&255),fout); /* hi */
  643. }
  644.  
  645.  
  646.